
import schema from 'async-validator';
import config from 'config';
import crypto from 'crypto';
import jwt from 'jsonwebtoken';
import { AUTHORITY } from 'ROOT/constants/common';
import { AppContext } from 'ROOT/interface/App';
import UserService from './user.service';
import { CryptoHelper, cryptoHelper2 } from 'ROOT/utils/crypto';


const sign = config.get<string>('sign');
const secretKey = config.get<string>('secretKey');
const userValidator = new schema({
    userName: {
        type: "string",
        required: true,
    },
    password: {
        type: "string",
        required: true,
    },
});

const inviteCodeMap: Record<string, number> = {}

export function get() {
    return UserService.find({});
}
/**
 *
 * @param {Koa.Context} ctx
 * @param {Function} next
 */
export const login = async (ctx: AppContext) => {
    const { i } = ctx.request.body as Record<string, any>;

    const {userName, password} = JSON.parse(cryptoHelper2.decrypt(i));
    try {
        await userValidator.validate({userName, password});
    } catch (error) {
        ctx.sendError({message: '用户名或密码为空'});
        return;
    }
    const passwordHex = crypto.createHmac('md5', sign)
                   .update(password)
                   .digest('hex');
    const res = await UserService.findOne({user: userName});
    if (!res || !res.id) {
        ctx.sendError({message: '用户名不存在'});
        return;
    }
    if (res.password !== passwordHex) {
        ctx.sendError({message: '账户或密码有误'});
        return;
    }
    // 签发token
    const userToken = {
        id: res.id,
        user: userName,
        role: res.role,
    }
    const token = jwt.sign(userToken, sign, {expiresIn: '7d'});  // 签发token
    ctx.session.token = token;

    try {
        encrypt(ctx);
    } catch (error) {
        console.log(error)
    }

    ctx.sendSuccess({
        data: userToken
    });
}

export const exit = async (ctx: AppContext) => {
    ctx.session.token = '';
    ctx.sendSuccess({});
}
/**
 *
 * @param {Koa.Context} ctx
 * @param {Function} next
 */
export const createUser = async (ctx: AppContext) => {
    const {userName, password, inviteCode } = ctx.request.body  as Record<string, any>;
    try {
        await userValidator.validate({userName, password});
    } catch ({errors}) {
        ctx.sendError({errors});
        return;
    }
    if (inviteCodeMap[inviteCode] == undefined) {
        ctx.sendError({message: '邀请码错误'});
        return;
    }
    const res = await UserService.find({user: userName});
    if (res.length !== 0) {
        ctx.sendError({message: '用户名已存在'});
        return;
    }

    try {
        const newUser = await UserService.create(userName, password, AUTHORITY.user);
        delete inviteCodeMap[inviteCode];
        // 签发token
        const userToken = {
            id: newUser.id,
            user: userName,
            role: newUser.role,
        }
        const token = jwt.sign(userToken, sign, {expiresIn: '7d'});  // 签发token
        ctx.session.token = token;
        encrypt(ctx);
        ctx.sendSuccess({
            data: userToken
        });
    } catch (err) {
        ctx.sendError({message: err});
    }
}

/**
 * 创建第一个用户
 * @param {Koa.Context} ctx
 * @param {Function} next
 */
export const createFirstUser = async (ctx: AppContext) => {
    const {userName, password} = ctx.query;
    try {
        await userValidator.validate({userName, password});
    } catch ({errors}) {
        ctx.sendError({errors});
        return;
    }
    const res = await UserService.find({});
    if (res.length !== 0) {
        ctx.sendError({message: '写入失败'});
        return;
    }
    const newUser = await UserService.create(userName as string, password as string, AUTHORITY.admin);
    if (newUser) {
        ctx.sendSuccess();
    } else {
        ctx.sendError({message: '写入失败'});
    }
}

/**
 * 获取用户信息
 */
export const userInfo = async (ctx: AppContext) => {


    if (!ctx.state.user) {
        ctx.sendError({message: '未登录', code: 401});
        return;
    }
    const user = await UserService.findOne({user: ctx.state.user.user});

  
    if (user) {
        const userData = {
            user: user.user,
            role: user.role,
            userid: user.id
        }
        encrypt(ctx);
        ctx.sendSuccess({data: userData});
        return;
    }
    ctx.sendError({message: 'Unlogin'});
}


export const  getInviteCode = async (ctx: AppContext) => {
    ctx.sendSuccess({data: Object.keys(inviteCodeMap)});
};
/** 生成邀请码,过期时间，保存内存中 */
export const  inviteCode = async (ctx: AppContext) => {
    // 生成随机数
    // string' is deprecated
    const code = Math.random().toString(36).substring(2);
    inviteCodeMap[code] = Date.now();
    ctx.sendSuccess({data: code});
};

function encrypt (ctx: AppContext) {
    const cryptoHelper = new CryptoHelper(`${ctx.headers['i']}${ctx.headers['key']}`);
    ctx.set('x0', cryptoHelper.encrypt(`${secretKey}`))
    ctx.set('x1', cryptoHelper.iv.toString())
}